package com.fenghuaxz.rpcframework;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * 创建 : 七羽软件工作室
 * 时间 : 2017/9/28 : 0:59
 */
public class BootstrapInBoundHandler extends ChannelDuplexHandler{

    private BaseContext context;
    private int timeoutSize = 0;
    private final IThreadPoolExecutor executor = IThreadPoolExecutor.newExecutor();

    public BootstrapInBoundHandler(BaseContext context){
        this.context = context;
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent){
            IdleStateEvent event= (IdleStateEvent) evt;
            if (event.state()== IdleState.READER_IDLE){
                if (++timeoutSize>3)ctx.channel().close();
            }else if (event.state()==IdleState.WRITER_IDLE){
                ctx.channel().writeAndFlush("ping");
            }else if (event.state()==IdleState.ALL_IDLE){
                ctx.channel().close();
            }
        }
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        this.context.group.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        this.context.group.remove(ctx.channel());
        OnClosedListener listener = this.context.closedListener;
        if (listener!=null)listener.onClosed(context,ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof String && "ping".equals(msg))
            timeoutSize=0;
        else{
            this.executor.submit(new RPCEventHandler(context,msg,ctx));
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.channel().close();
        Thread.UncaughtExceptionHandler ueh=Thread.getDefaultUncaughtExceptionHandler();
        if (ueh!=null)
            ueh.uncaughtException(Thread.currentThread(),cause);
        else{
            super.exceptionCaught(ctx, cause);
        }
    }
}
